using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;

/// <summary>
/// UI层级枚举
/// </summary>
public enum UI层级
{
    底层,中层,上层,系统层
}
public enum 事件类型
{
    鼠标进入,鼠标移出,鼠标按下,鼠标抬起,鼠标点击完成,
    拖动中,拖动结束前,滚轮,正在输入,点击输入框,输入完成,移动,
    初始化拖动,拖动开始,拖动结束,提交,取消
}

/// <summary>
/// 管理所有显示的面板
/// 提供给外部 显示或隐藏等等接口
/// </summary>
public class UI管理器 : 单例_基础管理器<UI管理器>
{

    public Dictionary<string, UI基类> 面板容器 = new Dictionary<string, UI基类>();

    private Transform 底层;
    private Transform 中层;
    private Transform 上层;
    private Transform 系统层;

    //UI 父对象
    public RectTransform 画布;

    public UI管理器()
    {
        GameObject obj = 资源管理器.获取实例.加载<GameObject>("UI/Canvas");
        this.画布 = obj.transform as RectTransform;
        obj.name = "Canvas";
        GameObject.DontDestroyOnLoad(obj);

        Transform 画布 = obj.transform;

        //分层
        底层 = 画布.Find("底层");
        中层 = 画布.Find("中层");
        上层 = 画布.Find("上层");
        系统层 = 画布.Find("系统层");

        obj = 资源管理器.获取实例.加载<GameObject>("UI/EventSystem");
        GameObject.DontDestroyOnLoad(obj);
    }

    public void 加载面板_并重命名<T>(string 面板名称, UI层级 层级 = UI层级.中层, UnityAction<T> 显示后操作 = null) where T : UI基类
    {
        int 重名数 = 0;
        string name = 面板名称;
        while (面板容器.ContainsKey(name))
        {
            name = 面板名称 + 重名数;
        }

        if (面板容器[面板名称] != null)//存在面板直接调用显示 并调用回调函数 然后 结束
        {
            面板容器[面板名称].显示面板();
            if (显示后操作 != null)
                显示后操作(面板容器[面板名称] as T);
            return;
        }

        资源管理器.获取实例.加载_异步<GameObject>("UI/" + 面板名称, (obj) =>
        {
            //放入Canvas的子对象
            //设置位置
            Transform 父级 = 底层;
            switch (层级)
            {
                case UI层级.中层:
                    父级 = 中层;
                    break;
                case UI层级.上层:
                    父级 = 上层;
                    break;
                case UI层级.系统层:
                    父级 = 系统层;
                    break;
                default:
                    break;
            }

            //设置相对位置和大小
            obj.transform.SetParent(父级);
            obj.transform.localPosition = Vector3.zero;
            obj.transform.localScale = Vector3.one;

            (obj.transform as RectTransform).offsetMax = Vector2.zero;
            (obj.transform as RectTransform).offsetMin = Vector2.zero;

            obj.name = name;

            T 面板 = obj.GetComponent<T>();
            if (显示后操作 != null)
                显示后操作(面板);
            面板.显示面板();
            面板.面板名 = 面板名称;
            面板容器.Add(name, 面板);
        });
    }


    /// <summary>
    /// 显示面板
    /// </summary>
    /// <typeparam name="T">面板脚本类型</typeparam>
    /// <param name="面板名称">面板名</param>
    /// <param name="层级">显示在哪一层</param>
    /// <param name="显示后操作">当创建好后需要做的事(初始化之类的)</param>
    public void 加载面板<T>(string 面板名称, UI层级 层级 = UI层级.中层, UnityAction<T> 显示后操作 = null) where T : UI基类
    {
        if (面板容器.ContainsKey(面板名称))//存在面板直接调用显示 并调用回调函数 然后 结束
        {
            if (面板容器[面板名称] != null)
            {
                面板容器[面板名称].显示面板();
                if (显示后操作 != null)
                    显示后操作(面板容器[面板名称] as T);
                return;
            }
        }
         资源管理器.获取实例.加载_异步<GameObject>("UI/" + 面板名称, (obj) =>
         {
             //放入Canvas的子对象
             //设置位置
             Transform 父级 = 底层;
             switch (层级)
             {
                 case UI层级.中层:
                     父级 = 中层;
                     break;
                 case UI层级.上层:
                     父级 = 上层;
                     break;
                 case UI层级.系统层:
                     父级 = 系统层;
                     break;
                 default:
                     break;
             }

             //设置相对位置和大小
             obj.transform.SetParent(父级);

             RectTransform ls = obj.transform as RectTransform;

             if (ls.anchorMax.x == 0.5f&& ls.anchorMax.y == 0.5f)
             {
                 obj.transform.localPosition = Vector3.zero;
             }
             else
             {
                 obj.transform.localPosition = Vector3.zero;
                 obj.transform.localScale = Vector3.one;

                 ls.offsetMax = Vector2.zero;
                 ls.offsetMin = Vector2.zero;
             }


             obj.name = 面板名称;

             T 面板 = obj.GetComponent<T>();
             if (显示后操作 != null)
                 显示后操作(面板);
             面板.显示面板();
             面板.面板名 = 面板名称;
             面板容器.Add(面板名称, 面板);
         });

    }


    public void 隐藏面板(string 面板名称)
    {
        if (面板容器.ContainsKey(面板名称))
            面板容器[面板名称].gameObject.SetActive(false);
    }



    public void 删除面板(string 面板名称)
    {
        if (面板容器.ContainsKey(面板名称))
        {
            //面板容器[面板名称].销毁面板();
            GameObject.Destroy(面板容器[面板名称].gameObject);
            面板容器.Remove(面板名称);
        }
    }

    public void 删除面板<T>(T 面板) where T : UI基类
    {
        if (面板容器.ContainsValue(面板))
        {
            foreach (var item in 面板容器)
            {
                if(面板容器[item.Key]==面板)
                {
                    面板容器.Remove(item.Key);
                    break;
                }
            }
            GameObject.Destroy(面板);
        }
    }

    /// <summary>
    /// 获取上中低图层
    /// </summary>
    /// <param name="层级"></param>
    /// <returns></returns>
    public Transform 得到要求的层级(UI层级 层级)
    {
        switch (层级)
        {
            case UI层级.底层:
                return 底层;
            case UI层级.中层:
                return 中层;
            case UI层级.上层:
                return 上层;
            case UI层级.系统层:
                return 系统层;
            default:
                return null;
        }
    }

    /// <summary>
    /// 得到已经显示的面板 方便外部使用
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="面板名"></param>
    /// <returns></returns>
    public T 得到面板<T>(string 面板名) where T : UI基类
    {
        if (面板容器.ContainsKey(面板名))
            return 面板容器[面板名] as T;
        return null;
    }


    public void 测试(EventTriggerType type)
    {
        type = EventTriggerType.Deselect;
    }

    private static EventTriggerType 转换(事件类型 类型)
    {
        switch (类型)
        {
            case 事件类型.鼠标进入:
                return EventTriggerType.PointerEnter;
            case 事件类型.鼠标移出:
                return EventTriggerType.PointerExit;
            case 事件类型.鼠标按下:
                return EventTriggerType.PointerDown;
            case 事件类型.鼠标抬起:
                return EventTriggerType.PointerUp;
            case 事件类型.鼠标点击完成:
                return EventTriggerType.PointerClick;
            case 事件类型.拖动中:
                return EventTriggerType.Drag;
            case 事件类型.拖动结束前:
                return EventTriggerType.Drop;
            case 事件类型.滚轮:
                return EventTriggerType.Scroll;
            case 事件类型.正在输入:
                return EventTriggerType.UpdateSelected;
            case 事件类型.点击输入框:
                return EventTriggerType.Select;
            case 事件类型.输入完成:
                return EventTriggerType.Deselect;
            case 事件类型.移动:
                return EventTriggerType.Move;
            case 事件类型.初始化拖动:
                return EventTriggerType.InitializePotentialDrag;
            case 事件类型.拖动开始:
                return EventTriggerType.BeginDrag;
            case 事件类型.拖动结束:
                return EventTriggerType.EndDrag;
            case 事件类型.提交:
                return EventTriggerType.Submit;
            case 事件类型.取消:
                return EventTriggerType.Cancel;
        }
        return EventTriggerType.Cancel;
    }

    /// <summary>
    /// 给控件添加自定义事件监听
    /// </summary>
    /// <param name="uI">控件对象</param>
    /// <param name="类型">事件类型</param>
    /// <param name="响应函数">事件的响应函数</param>
    public static void 添加自定义事件(UIBehaviour uI, 事件类型 类型, UnityAction<BaseEventData> 响应函数)
    {
        EventTrigger 触发器 = uI.GetComponent<EventTrigger>();
        if (触发器 == null)
            触发器 = uI.gameObject.AddComponent<EventTrigger>();

        EventTrigger.Entry 事件 = new EventTrigger.Entry();
        事件.eventID = 转换(类型);
        事件.callback.AddListener(响应函数);

        触发器.triggers.Add(事件);
    }
}
